#ifdef WIN32
#include <afx.h>
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif

#include "aes.h"
#include "aescode.h"

unsigned char iv[16] = {85, 60, 12, 116, 99, -67 + 256, -83 + 256, 19,
                -118 + 256, -73 + 256, -24 + 256, -8 + 256, 82, -24 + 256, -56 + 256,
                -14 + 256};

#define BLOCK_SIZE 16

TAesCode::TAesCode(char* key)
{
    m_decodeCtx = aes_decrypt_init((unsigned char*)key, 16);
    m_encodeCtx = aes_encrypt_init((unsigned char*)key, 16);
}

TAesCode::~TAesCode()
{
    aes_decrypt_deinit(m_decodeCtx);
    aes_encrypt_deinit(m_encodeCtx);
}

int TAesCode::encrypt_cbc(char* data, int length,char* out)
{
    u8 cbc[BLOCK_SIZE];
	memcpy(cbc, iv, BLOCK_SIZE);

    int blocks = length / BLOCK_SIZE;
    int x = length % BLOCK_SIZE;
	
    if (x != 0)
	{
		int padlen = 16 - x;
        memset(out,padlen,length + 16);
        blocks += 1;
	}
    memcpy(out,data,length);
	
	for (int i = 0; i < blocks; i++) {
		for (int j = 0; j < BLOCK_SIZE; j++)
			cbc[j] ^= out[j];
		aes_encrypt(m_encodeCtx, cbc, cbc);
		memcpy(out, cbc, BLOCK_SIZE);
		out += BLOCK_SIZE;
	}
    return blocks * BLOCK_SIZE;
}

int TAesCode::decrypt_cbc(char* data, int length)
{
    u8 cbc[BLOCK_SIZE], tmp[BLOCK_SIZE];
	u8 *pos = (unsigned char*)data;
	int i, j, blocks;

	memcpy(cbc, iv, BLOCK_SIZE);

	blocks = length / BLOCK_SIZE;
	for (i = 0; i < blocks; i++) {
		memcpy(tmp, pos, BLOCK_SIZE);
		aes_decrypt(m_decodeCtx, pos, pos);
		for (j = 0; j < BLOCK_SIZE; j++)
			pos[j] ^= cbc[j];
		memcpy(cbc, tmp, BLOCK_SIZE);
		pos += BLOCK_SIZE;
	}
	return 0;
}

void TAesCode::remove_padding(char* data, int length)
{
    for(int i=length;i>= 0;i--)
    {
        //unsigned char value = data[i];
        if(((unsigned char)data[i]) > 16)
        {
            data[i+1] =0;
            break;
        }
    }
}

int TAesCode::decrypt_cbc_full(char* data, int length)
{
    u8 cbc[BLOCK_SIZE], tmp[BLOCK_SIZE];
	u8 *pos = (unsigned char*)data;
	int i, j, blocks;

	memcpy(cbc, iv, BLOCK_SIZE);

	blocks = length / BLOCK_SIZE;
	for (i = 0; i < blocks; i++) {
		memcpy(tmp, pos, BLOCK_SIZE);
		aes_decrypt(m_decodeCtx, pos, pos);
		for (j = 0; j < BLOCK_SIZE; j++)
			pos[j] ^= cbc[j];
		memcpy(cbc, tmp, BLOCK_SIZE);
		pos += BLOCK_SIZE;
	}

    remove_padding(data,length);

	return 0;
}

int aes_test()
{
    char *key0="D915581AA2EF37B5";

    char* src = "12345678901234567890";
    char  enc_buf[512];
    TAesCode code2(key0);
    int outlen = code2.encrypt_cbc(src,strlen(src),enc_buf);
    

    TAesCode code(key0);
    for(int i=0;i<10;i++)
    {
        char dec_buf[1024]={0};
	    memcpy(dec_buf, enc_buf,outlen);
        
        code.decrypt_cbc(dec_buf, outlen);
        code.remove_padding(dec_buf,outlen);
        printf("dec buffer = %s\n",dec_buf);
    }
    return 0;

}
